/**
 * @file acl.c
 *
 * Copyright (C) Huawei Technologies Co., Ltd. 2023-2023. All Rights Reserved.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "acl/acl.h"
#include "log_inner.h"
#include "runtime/rt.h"
#include "framework/executor_c/ge_executor.h"

#if defined(__cplusplus)
extern "C" {
#endif
bool aclInitFlag = 0;
bool aclDeInitFlag = 0;

static inline bool PathIsLegal(const char *cfg) {
  int fd = open(cfg, O_RDONLY);
  if (fd < 0) {
    return false;
  }
  bool isLegal = lseek(fd, 0, SEEK_END) == 0 ? false : true;
  close(fd);
  return isLegal;
}

aclError aclInit(const char *configPath) {
  if (__sync_bool_compare_and_swap(&aclInitFlag, false, true)) {
    const rtError_t rtErr = rtInit();
    if (rtErr != RT_ERROR_NONE) {
      ACL_LOG_INNER_ERROR("runtime init fail, ret = %d", rtErr);
      return rtErr;
    }
    Status ret = GeInitialize();
    if (ret != SUCCESS) {
      ACL_LOG_INNER_ERROR("ge init fail, ret = %d", ret);
      rtDeinit();
      return ret;
    }
    if (PathIsLegal(configPath)) {
      ret = GeDbgInit(configPath);
      if (ret != SUCCESS) {
        (void)GeFinalize();
        rtDeinit();
        return ret;
      }
    }
  } else {
    ACL_LOG_INFO("[Initialize][Acl]repeatedly initialized");
    return ACL_ERROR_REPEAT_INITIALIZE;
  }
  ACL_LOG_INFO("successfully execute");
  return ACL_SUCCESS;
}

aclError aclFinalize() {
  if (__sync_bool_compare_and_swap(&aclDeInitFlag, false, true)) {
    (void)GeDbgDeInit();
    (void)GeFinalize();
    rtDeinit();
  } else {
    ACL_LOG_INNER_ERROR("[Finalize][Acl]repeatedly finalized");
    return ACL_ERROR_REPEAT_FINALIZE;
  }

  ACL_LOG_INFO("successfully execute");
  return ACL_SUCCESS;
}

aclError aclrtGetVersion(int32_t *majorVersion, int32_t *minorVersion,
                         int32_t *patchVersion) {
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(majorVersion);
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(minorVersion);
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(patchVersion);
  // Acl version is (*majorVersion).(*minorVersion).(*patchVersion)
  *majorVersion = ACL_MAJOR_VERSION;
  *minorVersion = ACL_MINOR_VERSION;
  *patchVersion = ACL_PATCH_VERSION;
  ACL_LOG_INFO("acl version is %d.%d.%d", *majorVersion, *minorVersion,
               *patchVersion);

  return ACL_SUCCESS;
}

const char *aclGetRecentErrMsg() {
  return GetErrorMessage();
}

#if defined(__cplusplus)
}
#endif